// 转换16进制字符串为字节
export function unhexlify(hex) {
    let str = hex.replace(/ /g, '');
    let arr = [];
    for (let i = 0; i < str.length; i += 2) {
        arr.push(parseInt(str.substr(i, 2), 16));
    }
    return arr;
}

// CRC16 Zero calculation (with reversed bits and little-endian)
export function crc16Zero(s) {
    const polynomial = 0x18005; // Correct polynomial for CRC16
    const initCrc = 0x0000;
    const xorOut = 0x0000;

    // Generate CRC function without bit reversal
    const crcFun = mkCrcFun(polynomial, false, initCrc, xorOut);

    // Calculate CRC and format output
    return getCrcValue(s, crcFun);
}

// Get the CRC value from the string and CRC function
export function getCrcValue(s, crc16) {
    let data = s.replace(' ', '');  // Remove spaces from the input string
    let crcOut = crc16(unhexlify(data));  // Calculate CRC
    let crcHex = (crcOut & 0xffff).toString(16).toUpperCase();  // Convert CRC to hex string

    // Ensure the result is at least 4 characters long, adding leading zeros if necessary
    while (crcHex.length < 4) {
        crcHex = '0' + crcHex;
    }

    // Check the format (you could also explicitly ensure it's lowercase)
    return parseInt(crcHex, 16);
}


// CRC function using polynomial and other parameters (bit reversal)
export function mkCrcFun(polynomial, rev, initCrc, xorOut) {
    return function (data) {
        let crc = initCrc;

        for (let i = 0; i < data.length; i++) {
            let byte = data[i];
            if (rev) byte = reverseBits(byte); // Bit reversal if needed
            for (let bit = 7; bit >= 0; bit--) {
                let bitValue = (byte >> bit) & 1;
                let xor = ((crc >> 15) & 1) ^ bitValue;
                crc = (crc << 1) & 0xFFFF;
                if (xor) {
                    crc = crc ^ polynomial;
                }
            }
        }
        return crc ^ xorOut;
    };
}

// Reverse bits in a byte (8 bits)
export function reverseBits(byte) {
    let rev = 0;
    for (let i = 0; i < 8; i++) {
        rev = (rev << 1) | (byte & 1);
        byte >>= 1;
    }
    return rev;
}
